/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package TablaSimbolos;

import java.util.LinkedHashMap;
import java.util.Map;
/**
 *
 * @author Diego
 */
public class entradaMetodo extends entradaTS{
    int offsetMethod = -1;
    int cantidadParametros; //indica la cantidad de parametros que tiene el metodo
    entradaClase retorno; 
    String label; //etiqueta generada- Las usadas en la VT.
    String perteneceaClase;//indica el nombre de la clase a la que pertenece 
    String mensajeError;
    boolean definido; //indica si el metodo fue definido.
    boolean esconstructor;
    LinkedHashMap <String,entradaParametro> tablaParametros = new LinkedHashMap();
    int lineaerror;

    public void setLineaError(int le){
        lineaerror = le;
    }
    
    public LinkedHashMap<String, entradaParametro> getTablaParametros() {
        return tablaParametros;
    }

    public boolean isDefinido() {
        return definido;
    }
    
    /**************************************************************************/
    /* Metodos de la clase entradaMetodo
    /**************************************************************************/
    
    /**
     * Setea el metodo definido cuando es encontrado en el class.
     */
    public void setearDefinido()
    {
        definido=true;
        /*
        entradaMetodo a =  new entradaMetodo(label, nombre);
        entradaTS b = new entradaTS(nombre);
        b= a;
        a = b;*/
        
    }    
    
    /**
     * Consulta si el retorno del metodo actual tiene el mismo nombre que se esta
     * pasando por parametro. Ejemplo int met1() si se quiere consultar si el 
     * retorno es de tipo "int" debera devolver true pero si se consulta por ejemplo
     * si es "char" devuelve falso.
     * @param r se quiere saber si el tipo de retorno tiene el mismo nombre que r.
     * @return true si r es igual al nombre del tipo del retorno del metodo, falso 
     * en caso contrario.
     */
    
    public boolean esMismoRetorno(String r)
    {
        return this.retorno.darNombre().compareTo(r)==0;
    }
    
    /**
     * Setea el tipo de retorno
     */
    public void setearRetorno(entradaClase tr)
    {
        retorno=tr;
    }
            
    /**
     * Devuelve el valor de retorno del metodo el cual puede ser uno de los 
     * siguientes:
     * - Primitivo: int, char, boolean, String (que tambien es una instancia de 
     *              entradaClase.
     * - void: tipo void
     * - De Clase: donde es una entradaClase.
     * @return Indica de que tipo es el retorno del metodo.
     */
    
    public entradaClase darRetornoMetodo()
    {
        return retorno;
    }
    
    /**
     * Indica si el metodo fue definido, es decir; se implemento el metodo en 
     * el class.
     * @return boolean True si el metodo fue definido en el class, false caso 
     * contrario
     */
    
    public boolean estaMetodoDefinido()
    {
        return definido;
    }
    
        
    /**
     * Setea el nombre de la clase a la que pertenece el metodo actual
     * @param nombreclass es el nombre de la clase a la que pertenece el 
     * metodo
     */
          
    public void setearPerteneceClase(String nombreclass)
    {
        perteneceaClase=nombreclass;
    }
    
    /**
     * Devuelve el nombre de la clase a la que pertenece el metodo.
     * @return String retorna el nombre de la clase donde se encuentra el metodo.
     */
    
    public String darNombreClasePertenece()
    {
        return perteneceaClase;
    }
    
    /**
     * Setea el nombre de la etiqueta del metodo.
     * @param lbl Indica que nombre tendra el atributo label que fue generado.
     */
    
    public void setearEtiqueta(String lbl)
    {
        label = lbl;
    }
        
    /**
     * Devuelve la etiqueta del metodo.
     * @return String Retorna el nombre de la etiqueta que tiene el metodo.
     */
    
    public String darEtiqueta()
    {
        return label;
    }
    
    /**
     * Setea el offset del metodo.
     * @param offsm indica que offset debe tener el metodo.
     */
    
    public void setearOffsetMethod(int offsm)
    {
        offsetMethod=offsm;
    }
    
    /**
     * Devuelve el offset que tiene el metodo.
     * @return int devuelve un entero que indica el offset del metodo.
     */
    
    public int darOffsetMethod()
    {
        return offsetMethod;
    }
    
    /**
     * Indica la cantidad de parametros que tiene el metodo
     * Ej: met(int x, char y)=2
     * @return int devuelve el la cantidad de parametros del metodo.
     */
    
    public int darCantParametros()
    {
        return cantidadParametros;
    }
    
    /**
     * Setea la cantidad de parametros que tiene el metodo.
     */
    public void setearCantParametros(int cant)
    {
        cantidadParametros=cant;
    }
    
    /**
     * Devuelve verdadero si es el constructor de la clase
     * @return boolean devuelve verdadero si es un constructor, falso en caso 
     * contrario.
     */
    public boolean esConstructorDeClase()
    {
        return esconstructor;
    }
    
    /**
     * Setea la entradaMetodo como un constructor de la clase.
     * 
     */
    public void setearEsConstructor()
    {
        esconstructor=true;
    }
    
    /**
     * Devuelve verdadero si el nombre del parametro que se intenta consultar
     * existe en la tabla de parametros.
     * @param nameOfParametro representa el nombre del parametro que se quiere
     * consultar a la tabla de parametros por su existencia. En caso de no existir
     * el metodo retorna falso.
     */
    public boolean perteneceTP(String nameOfParametro)
    {
        if (this.tablaParametros.get(nameOfParametro)!=null)
        {
            return true;
        }
        else 
        {
            return false;
        }
    }
    
    /**
     * Devuelve si existe en la tabla de parametros una entradaParametro con
     * con nombre nameOfParametro. Es decir busca un parametro con un nombre 
     * determinado en la tabla de parametros.
     * @param nameOfParametro es el nombre del parametro que se quiere buscar 
     * en la tabla de parametros.
     * @return entradaParametro Devuelve una entradaParametro que se corresponde 
     * con el nombre del parametro pasado al metodo. en caso de no existir devuelve
     * null.
     */
    public entradaParametro darParametro(String nameOfParametro)
    {
        if (perteneceTP(nameOfParametro))
      {  
          return this.tablaParametros.get(nameOfParametro);
      }
      else
      {
          return null;
      }
    }
    
    /**
     * Agrega un nuevo parametro a la tabla de parametros del metodo.
     * @param ep Es el parametro que se quiere agregar al metodo.
     * @throws Exception Arroja un error en caso de que el nombre del parametro
     * ya haya sido utilizado previamente por otro parametro o que tenga el 
     * mismo nombre que el metodo o tenga el mismo nombre que la clase.
     */
    public void insertarParametro(entradaParametro ep)throws Exception
    {
        String m;
        if (!this.perteneceTP(ep.darNombre()))
        {
            if (!(ep.darNombre().compareTo(this.darNombreClasePertenece())==0))
            {
                if (!(ep.darNombre().compareTo(this.darNombre())==0))
                { 
                    this.tablaParametros.put(ep.darNombre(),ep);
                }
                else
                {
                    m="Intenta usar el nombre del metodo "+ep.darNombre()+" como nombre de un parametro. ";
                    mensajeError = errorTS.construirErrorTS(m, lineaerror);
                    throw new errorTS(mensajeError);
                }
            }
            else
            {
                m="Intenta usar el nombre de la clase "+ep.darNombre()+" como nombre de parametro en el metodo "
                + ep.darNombreMetodoP();                  
                mensajeError = errorTS.construirErrorTS(m, lineaerror);
                throw new errorTS(mensajeError);
            }
        }
        else
        {
                m="El nombre "+ep.darNombre()+" ya fue usado por otro parametro. ";
                mensajeError = errorTS.construirErrorTS(m, lineaerror);
                throw new errorTS(mensajeError);
        }
    }
    
    /**
     * Muestra por pantalla los parametros del metodo en caso de existir
     */
    
    public void mostrarTodosLosParametros()
    {
        //Iterator iter = this.tablaParametros.entrySet().iterator();
        //Map.Entry e;
        entradaParametro ep;
        String tipop,namep;
        for (Map.Entry entry : this.tablaParametros.entrySet()) 
        {
            ep=this.darParametro((String)entry.getKey());
            tipop=ep.toStringTipoP();
            namep=ep.darNombre();
            System.out.println("Lista de parametros :");
            System.out.print("Tipo:");
            System.out.println(tipop);
            System.out.print("Identificador : ");
            System.out.println(namep);   
            ep.mostrarAtributosParametro();
            
        }        
    }
    
    /**************************************************************************/
    /* Constructor de la clase entradaMetodo
    /**************************************************************************/
    
    /**
     * Constructor de la clase entradaMetodos.
     * @param l Setea el atributo label con el nombre de la etiqueta que es usada
     * en la generacion de codigo intermedio
     * @param nameofclass Setea el nombre de la clase a la que pertenece el metodo
     * @param nameofmethod Setea el nombre del metodo.
     */
    
    public entradaMetodo(String nameofclass, String nameofmethod)
    {
        super(nameofmethod);        
        perteneceaClase=nameofclass;
        definido=false;        
        esconstructor=false; //por defecto se asume que no es un constructor
        retorno=null; 
        cantidadParametros=0;        
    }    
}